#pragma once
#include "Log.hpp"
#include <arpa/inet.h>
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include<iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include<sys/types.h>

class Sock
{
public:
    Sock(){}
    int Socket()
    {
        int serversock=socket(AF_INET, SOCK_DGRAM, 0);
        if(serversock < 0)
        {
            LogMessage(FATAL, "%d:%s",errno, strerror(errno));
            exit(-1);
        }
        LogMessage(NORMAL, "socket() finish");
        return serversock;
    }
    void Bind(int sock,uint16_t port,std::string ip="0.0.0.0")
    {
        //这里要对地址进行初始化以后才能够绑定到一起
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        //这里的绑定就是要把sock和地址结构绑定到一起
        server.sin_family=AF_INET;
        server.sin_port=htons(port);
        server.sin_addr.s_addr=inet_addr(ip.c_str());
        if(bind(sock, (struct sockaddr*)&server, len) < 0)
        {
            LogMessage(FATAL, "%d:%s",errno, strerror(errno));
            exit(-1);
        }
    }
    void Listen(int sock)
    {
        if(listen(sock, gbackLog) < 0)
        {
            LogMessage(FATAL, "%d:%s", errno,strerror(errno));
            exit(-1);
        }
        LogMessage(NORMAL, "init server success");
    }
    //这里所要接受的本身就是客户端的套接字
    int Accept(int sock,uint16_t* port,std::string* ip)
    {
        struct sockaddr_in client;
        socklen_t len=sizeof(client);
        int serversock=accept(sock, (struct sockaddr*)&client, &len);
        if(serversock < 0)
        {
            LogMessage(FATAL, "%d:%s", errno,strerror(errno));
            exit(-1);
        }
        if(port){
            *port=ntohs(client.sin_port);
        }
        if(ip){
            *ip=inet_ntoa(client.sin_addr);
        }
        return serversock; 
    }
    bool Cannect(int sock,uint16_t& port,std::string& ip)
    {
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        memset(&server, 0, sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(port);
        server.sin_addr.s_addr=inet_addr(ip.c_str());
        if(connect(sock, (struct sockaddr*)&server, len) < 0)
        {
            LogMessage(FATAL, "%d:%s", errno,strerror(errno));
            return true;
        }
        else{
            return false;
        }
    }
private:
    const int gbackLog=20;
};
